home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue50 / Except / HVPEUtils.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-09-06  |  22.1 KB  |  533 lines

  1. unit HVPEUtils;
  2. { PE-file types missing from the Windows and ImageHlp units.
  3.   These were gleaned from Matt Pietrek's work and WINNT.H
  4.  
  5.   And simple utility routines to access parts of a loaded PE file.
  6.  
  7.   Written by Hallvard Vassbotn, hallvard@balder.no, July 1999
  8.  
  9.   Inspired by Matt Pietrek's article "Peering inside the PE: A Tour of the Win32
  10.   Portable Executable File Format", available at:
  11.      http://msdn.microsoft.com/library/techart/msdn_peeringpe.htm
  12. }
  13. interface
  14.  
  15. uses
  16.   Windows,
  17.   SysUtils;
  18.  
  19. // ------------------------- START-OF-WINNT.H-STUFF ---------------------------
  20.  
  21. {$IFDEF VER90}
  22. // The Delphi 2.0 version of the Windows unit lacks some key definitions:
  23.  
  24. const
  25.   IMAGE_DOS_SIGNATURE                     = $5A4D;
  26.   IMAGE_NT_SIGNATURE                      = $00004550;
  27.   IMAGE_NUMBEROF_DIRECTORY_ENTRIES        = 16;
  28.   IMAGE_SIZEOF_SHORT_NAME                  = 8;
  29.   IMAGE_DIRECTORY_ENTRY_IMPORT             = 1;
  30.  
  31. type
  32.   PImageFileHeader = ^TImageFileHeader;
  33.   TImageFileHeader = packed record
  34.     Machine: Word;
  35.     NumberOfSections: Word;
  36.     TimeDateStamp: DWORD;
  37.     PointerToSymbolTable: DWORD;
  38.     NumberOfSymbols: DWORD;
  39.     SizeOfOptionalHeader: Word;
  40.     Characteristics: Word;
  41.   end;
  42.  
  43.   PImageDataDirectory = ^TImageDataDirectory;
  44.   TImageDataDirectory = record
  45.     VirtualAddress: DWORD;
  46.     Size: DWORD;
  47.   end;
  48.  
  49.   PimageOptionalHeader = ^TImageOptionalHeader;
  50.   TImageOptionalHeader = packed record
  51.     { Standard fields. }
  52.     Magic: Word;
  53.     MajorLinkerVersion: Byte;
  54.     MinorLinkerVersion: Byte;
  55.     SizeOfCode: DWORD;
  56.     SizeOfInitializedData: DWORD;
  57.     SizeOfUninitializedData: DWORD;
  58.     AddressOfEntryPoint: DWORD;
  59.     BaseOfCode: DWORD;
  60.     BaseOfData: DWORD;
  61.     { NT additional fields. }
  62.     ImageBase: DWORD;
  63.     SectionAlignment: DWORD;
  64.     FileAlignment: DWORD;
  65.     MajorOperatingSystemVersion: Word;
  66.     MinorOperatingSystemVersion: Word;
  67.     MajorImageVersion: Word;
  68.     MinorImageVersion: Word;
  69.     MajorSubsystemVersion: Word;
  70.     MinorSubsystemVersion: Word;
  71.     Win32VersionValue: DWORD;
  72.     SizeOfImage: DWORD;
  73.     SizeOfHeaders: DWORD;
  74.     CheckSum: DWORD;
  75.     Subsystem: Word;
  76.     DllCharacteristics: Word;
  77.     SizeOfStackReserve: DWORD;
  78.     SizeOfStackCommit: DWORD;
  79.     SizeOfHeapReserve: DWORD;
  80.     SizeOfHeapCommit: DWORD;
  81.     LoaderFlags: DWORD;
  82.     NumberOfRvaAndSizes: DWORD;
  83.     DataDirectory: packed array[0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES-1] of TImageDataDirectory;
  84.   end;
  85.  
  86.   PImageNtHeaders = ^TImageNtHeaders;
  87.   TImageNtHeaders = packed record
  88.     Signature: DWORD;
  89.     FileHeader: TImageFileHeader;
  90.     OptionalHeader: TImageOptionalHeader;
  91.   end;
  92.  
  93.   TISHMisc = packed record
  94.     case Integer of
  95.       0: (PhysicalAddress: DWORD);
  96.       1: (VirtualSize: DWORD);
  97.   end;
  98.  
  99.   PImageSectionHeader = ^TImageSectionHeader;
  100.   TImageSectionHeader = packed record
  101.     Name: packed array[0..IMAGE_SIZEOF_SHORT_NAME-1] of Byte;
  102.     Misc: TISHMisc;
  103.     VirtualAddress: DWORD;
  104.     SizeOfRawData: DWORD;
  105.     PointerToRawData: DWORD;
  106.     PointerToRelocations: DWORD;
  107.     PointerToLinenumbers: DWORD;
  108.     NumberOfRelocations: Word;
  109.     NumberOfLinenumbers: Word;
  110.     Characteristics: DWORD;
  111.   end;
  112. {$ENDIF}
  113.  
  114. const
  115.   MaxBlock = MaxInt-$f;
  116. type
  117.   LONG = DWORD;
  118.   PImageDOSHeader = ^TImageDosHeader;
  119.   TImageDOSHeader = packed record        // DOS .EXE header
  120.     e_magic:    WORD;                    // Magic number
  121.     e_cblp:     WORD;                    // Bytes on last page of file
  122.     e_cp:       WORD;                    // Pages in file
  123.     e_crlc:     WORD;                    // Relocations
  124.     e_cparhdr:  WORD;                    // Size of header in paragraphs
  125.     e_minalloc: WORD;                    // Minimum extra paragraphs needed
  126.     e_maxalloc: WORD;                    // Maximum extra paragraphs needed
  127.     e_ss:       WORD;                    // Initial (relative) SS value
  128.     e_sp:       WORD;                    // Initial SP value
  129.     e_csum:     WORD;                    // Checksum
  130.     e_ip:       WORD;                    // Initial IP value
  131.     e_cs:       WORD;                    // Initial (relative) CS value
  132.     e_lfarlc:   WORD;                    // File address of relocation table
  133.     e_ovno:     WORD;                    // Overlay number
  134.     e_res:      array[0..4-1] of WORD;   // Reserved words
  135.     e_oemid:    WORD;                    // OEM identifier (for e_oeminfo)
  136.     e_oeminfo:  WORD;                    // OEM information: e_oemid specific
  137.     e_res2:     array[0..10-1] of WORD;  // Reserved words
  138.     e_lfanew:   LONG;                    // File address of new exe header
  139.   end;
  140.  
  141.   PImageOS2Header = ^TImageOS2Header;
  142.   TImageOS2Header = packed record        // OS/2 .EXE header
  143.     ne_magic:        WORD;               // Magic number
  144.     ne_ver:          CHAR;               // Version number
  145.     ne_rev:          CHAR;               // Revision number
  146.     ne_enttab:       WORD;               // Offset of Entry Table
  147.     ne_cbenttab:     WORD;               // Number of bytes in Entry Table
  148.     ne_crc:          LONG;               // Checksum of whole file
  149.     ne_flags:        WORD;               // Flag WORD;
  150.     ne_autodata:     WORD;               // Automatic data segment number
  151.     ne_heap:         WORD;               // Initial heap allocation
  152.     ne_stack:        WORD;               // Initial stack allocation
  153.     ne_csip:         LONG;               // Initial CS:IP setting
  154.     ne_sssp:         LONG;               // Initial SS:SP setting
  155.     ne_cseg:         WORD;               // Count of file segments
  156.     ne_cmod:         WORD;               // Entries in Module Reference Table
  157.     ne_cbnrestab:    WORD;               // Size of non-resident name table
  158.     ne_segtab:       WORD;               // Offset of Segment Table
  159.     ne_rsrctab:      WORD;               // Offset of Resource Table
  160.     ne_restab:       WORD;               // Offset of resident name table
  161.     ne_modtab:       WORD;               // Offset of Module Reference Table
  162.     ne_imptab:       WORD;               // Offset of Imported Names Table
  163.     ne_nrestab:      LONG;               // Offset of Non-resident Names Table
  164.     ne_cmovent:      WORD;               // Count of movable entries
  165.     ne_align:        WORD;               // Segment alignment shift count
  166.     ne_cres:         WORD;               // Count of resource segments
  167.     ne_exetyp:       BYTE;               // Target Operating system
  168.     ne_flagsothers:  BYTE;               // Other .EXE flags
  169.     ne_pretthunks:   WORD;               // offset to return thunks
  170.     ne_psegrefbytes: WORD;               // offset to segment ref. bytes
  171.     ne_swaparea:     WORD;               // Minimum code swap area size
  172.     ne_expver:       WORD;               // Expected Windows version number
  173.   end;
  174.  
  175.   PImageVXDHeader = ^TImageVXDHeader;
  176.   TImageVXDHeader = packed record       // Windows VXD header
  177.     e32_magic:        WORD;              // Magic number
  178.     e32_border:       BYTE;              // The byte ordering for the VXD
  179.     e32_worder:       BYTE;              // The word ordering for the VXD
  180.     e32_level:        DWORD;             // The EXE format level for now = 0
  181.     e32_cpu:          WORD;              // The CPU type
  182.     e32_os:           WORD;              // The OS type
  183.     e32_ver:          DWORD;             // Module version
  184.     e32_mflags:       DWORD;             // Module flags
  185.     e32_mpages:       DWORD;             // Module # pages
  186.     e32_startobj:     DWORD;             // Object # for instruction pointer
  187.     e32_eip:          DWORD;             // Extended instruction pointer
  188.     e32_stackobj:     DWORD;             // Object # for stack pointer
  189.     e32_esp:          DWORD;             // Extended stack pointer
  190.     e32_pagesize:     DWORD;             // VXD page size
  191.     e32_lastpagesize: DWORD;             // Last page size in VXD
  192.     e32_fixupsize:    DWORD;             // Fixup section size
  193.     e32_fixupsum:     DWORD;             // Fixup section checksum
  194.     e32_ldrsize:      DWORD;             // Loader section size
  195.     e32_ldrsum:       DWORD;             // Loader section checksum
  196.     e32_objtab:       DWORD;             // Object table offset
  197.     e32_objcnt:       DWORD;             // Number of objects in module
  198.     e32_objmap:       DWORD;             // Object page map offset
  199.     e32_itermap:      DWORD;             // Object iterated data map offset
  200.     e32_rsrctab:      DWORD;             // Offset of Resource Table
  201.     e32_rsrccnt:      DWORD;             // Number of resource entries
  202.     e32_restab:       DWORD;             // Offset of resident name table
  203.     e32_enttab:       DWORD;             // Offset of Entry Table
  204.     e32_dirtab:       DWORD;             // Offset of Module Directive Table
  205.     e32_dircnt:       DWORD;             // Number of module directives
  206.     e32_fpagetab:     DWORD;             // Offset of Fixup Page Table
  207.     e32_frectab:      DWORD;             // Offset of Fixup Record Table
  208.     e32_impmod:       DWORD;             // Offset of Import Module Name Table
  209.     e32_impmodcnt:    DWORD;             // Number of entries in Import Module Name Table
  210.     e32_impproc:      DWORD;             // Offset of Import Procedure Name Table
  211.     e32_pagesum:      DWORD;             // Offset of Per-Page Checksum Table
  212.     e32_datapage:     DWORD;             // Offset of Enumerated Data Pages
  213.     e32_preload:      DWORD;             // Number of preload pages
  214.     e32_nrestab:      DWORD;             // Offset of Non-resident Names Table
  215.     e32_cbnrestab:    DWORD;             // Size of Non-resident Name Table
  216.     e32_nressum:      DWORD;             // Non-resident Name Table Checksum
  217.     e32_autodata:     DWORD;             // Object # for automatic data object
  218.     e32_debuginfo:    DWORD;             // Offset of the debugging information
  219.     e32_debuglen:     DWORD;             // The length of the debugging info. in bytes
  220.     e32_instpreload:  DWORD;             // Number of instance pages in preload section of VXD file
  221.     e32_instdemand:   DWORD;             // Number of instance pages in demand load section of VXD file
  222.     e32_heapsize:     DWORD;             // Size of heap - for 16-bit apps
  223.     e32_res3:         array[0..12-1] of BYTE; // Reserved words
  224.     e32_winresoff:    DWORD;
  225.     e32_winreslen:    DWORD;
  226.     e32_devid:        WORD;              // Device ID for VxD
  227.     e32_ddkver:       WORD;              // DDK version for VxD
  228.   end;
  229.  
  230. // Convert to function?
  231. {##define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER)        \
  232.     ((DWORD)ntheader +                                                  \
  233.      FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) +                 \
  234.      ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader   \
  235.     ))}
  236.  
  237. //
  238. // Relocation format.
  239. //
  240.   PImageRelocation = ^TImageRelocation;
  241.   TImageRelocation = packed record
  242.     case integer of
  243.       0 : (VirtualAddress    : DWORD;
  244.            SymbolTableIndex  : DWORD;
  245.            RelocType         : WORD);
  246.       1 : (RelocCount        : DWORD; // Set to the real count when IMAGE_SCN_LNK_NRELOC_OVFL is set
  247.            SymbolTableIndex_ : DWORD;
  248.            RelocType_        : WORD);
  249.   end;
  250. const
  251.  IMAGE_SIZEOF_RELOCATION = 10;
  252.  
  253. const
  254. //
  255. // I386 relocation types.
  256. //
  257.   IMAGE_REL_I386_ABSOLUTE         = $0000;  // Reference is absolute, no relocation is necessary
  258.   IMAGE_REL_I386_DIR16            = $0001;  // Direct 16-bit reference to the symbols virtual address
  259.   IMAGE_REL_I386_REL16            = $0002;  // PC-relative 16-bit reference to the symbols virtual address
  260.   IMAGE_REL_I386_DIR32            = $0006;  // Direct 32-bit reference to the symbols virtual address
  261.   IMAGE_REL_I386_DIR32NB          = $0007;  // Direct 32-bit reference to the symbols virtual address, base not included
  262.   IMAGE_REL_I386_SEG12            = $0009;  // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address
  263.   IMAGE_REL_I386_SECTION          = $000A;
  264.   IMAGE_REL_I386_SECREL           = $000B;
  265.   IMAGE_REL_I386_REL32            = $0014;  // PC-relative 32-bit reference to the symbols virtual address
  266.  
  267. //
  268. // MIPS relocation types.
  269. //
  270.   IMAGE_REL_MIPS_ABSOLUTE         = $0000; // Reference is absolute, no relocation is necessary
  271.   IMAGE_REL_MIPS_REFHALF          = $0001;
  272.   IMAGE_REL_MIPS_REFWORD          = $0002;
  273.   IMAGE_REL_MIPS_JMPADDR          = $0003;
  274.   IMAGE_REL_MIPS_REFHI            = $0004;
  275.   IMAGE_REL_MIPS_REFLO            = $0005;
  276.   IMAGE_REL_MIPS_GPREL            = $0006;
  277.   IMAGE_REL_MIPS_LITERAL          = $0007;
  278.   IMAGE_REL_MIPS_SECTION          = $000A;
  279.   IMAGE_REL_MIPS_SECREL           = $000B;
  280.   IMAGE_REL_MIPS_SECRELLO         = $000C; // Low 16-bit section relative referemce (used for >32k TLS)
  281.   IMAGE_REL_MIPS_SECRELHI         = $000D; // High 16-bit section relative reference (used for >32k TLS)
  282.   IMAGE_REL_MIPS_REFWORDNB        = $0022;
  283.   IMAGE_REL_MIPS_PAIR             = $0025;
  284.  
  285. //
  286. // Alpha Relocation types.
  287. //
  288.   IMAGE_REL_ALPHA_ABSOLUTE        = $0000;
  289.   IMAGE_REL_ALPHA_REFLONG         = $0001;
  290.   IMAGE_REL_ALPHA_REFQUAD         = $0002;
  291.   IMAGE_REL_ALPHA_GPREL32         = $0003;
  292.   IMAGE_REL_ALPHA_LITERAL         = $0004;
  293.   IMAGE_REL_ALPHA_LITUSE          = $0005;
  294.   IMAGE_REL_ALPHA_GPDISP          = $0006;
  295.   IMAGE_REL_ALPHA_BRADDR          = $0007;
  296.   IMAGE_REL_ALPHA_HINT            = $0008;
  297.   IMAGE_REL_ALPHA_INLINE_REFLONG  = $0009;
  298.   IMAGE_REL_ALPHA_REFHI           = $000A;
  299.   IMAGE_REL_ALPHA_REFLO           = $000B;
  300.   IMAGE_REL_ALPHA_PAIR            = $000C;
  301.   IMAGE_REL_ALPHA_MATCH           = $000D;
  302.   IMAGE_REL_ALPHA_SECTION         = $000E;
  303.   IMAGE_REL_ALPHA_SECREL          = $000F;
  304.   IMAGE_REL_ALPHA_REFLONGNB       = $0010;
  305.   IMAGE_REL_ALPHA_SECRELLO        = $0011;  // Low 16-bit section relative reference
  306.   IMAGE_REL_ALPHA_SECRELHI        = $0012;  // High 16-bit section relative reference
  307.  
  308. //
  309. // IBM PowerPC relocation types.
  310. //
  311.   IMAGE_REL_PPC_ABSOLUTE          = $0000;  // NOP
  312.   IMAGE_REL_PPC_ADDR64            = $0001;  // 64-bit address
  313.   IMAGE_REL_PPC_ADDR32            = $0002;  // 32-bit address
  314.   IMAGE_REL_PPC_ADDR24            = $0003;  // 26-bit address, shifted left 2 (branch absolute)
  315.   IMAGE_REL_PPC_ADDR16            = $0004;  // 16-bit address
  316.   IMAGE_REL_PPC_ADDR14            = $0005;  // 16-bit address, shifted left 2 (load doubleword)
  317.   IMAGE_REL_PPC_REL24             = $0006;  // 26-bit PC-relative offset, shifted left 2 (branch relative)
  318.   IMAGE_REL_PPC_REL14             = $0007;  // 16-bit PC-relative offset, shifted left 2 (br cond relative)
  319.   IMAGE_REL_PPC_TOCREL16          = $0008;  // 16-bit offset from TOC base
  320.   IMAGE_REL_PPC_TOCREL14          = $0009;  // 16-bit offset from TOC base, shifted left 2 (load doubleword)
  321.   IMAGE_REL_PPC_ADDR32NB          = $000A;  // 32-bit addr w/o image base
  322.   IMAGE_REL_PPC_SECREL            = $000B;  // va of containing section (as in an image sectionhdr)
  323.   IMAGE_REL_PPC_SECTION           = $000C;  // sectionheader number
  324.   IMAGE_REL_PPC_IFGLUE            = $000D;  // substitute TOC restore instruction iff symbol is glue code
  325.   IMAGE_REL_PPC_IMGLUE            = $000E;  // symbol is glue code; virtual address is TOC restore instruction
  326.   IMAGE_REL_PPC_SECREL16          = $000F;  // va of containing section (limited to 16 bits)
  327.   IMAGE_REL_PPC_REFHI             = $0010;
  328.   IMAGE_REL_PPC_REFLO             = $0011;
  329.   IMAGE_REL_PPC_PAIR              = $0012;
  330.  
  331.   IMAGE_REL_PPC_TYPEMASK          = $00FF;  // mask to isolate above values in IMAGE_RELOCATION.Type
  332.  
  333. // Flag bits in IMAGE_RELOCATION.TYPE
  334.  
  335.   IMAGE_REL_PPC_NEG               = $0100;  // subtract reloc value rather than adding it
  336.   IMAGE_REL_PPC_BRTAKEN           = $0200;  // fix branch prediction bit to predict branch taken
  337.   IMAGE_REL_PPC_BRNTAKEN          = $0400;  // fix branch prediction bit to predict branch not taken
  338.   IMAGE_REL_PPC_TOCDEFN           = $0800;  // toc slot defined in file (or, data in toc)
  339.  
  340. //
  341. // Based relocation format.
  342. //
  343. type
  344.   PImageBaseRelocation = ^TImageBaseRelocation;
  345.   TImageBaseRelocation = packed record
  346.     VirtualAddress: DWORD;
  347.     SizeOfBlock   : DWORD;
  348.     TypeOffsets   : Array[0..MaxBlock div SizeOf(WORD)] of WORD;
  349.   end;
  350.  
  351. const
  352.   IMAGE_SIZEOF_BASE_RELOCATION        = 8;
  353.  
  354. //
  355. // Based relocation types.
  356. //
  357.  
  358.   IMAGE_REL_BASED_ABSOLUTE             = 0;
  359.   IMAGE_REL_BASED_HIGH                 = 1;
  360.   IMAGE_REL_BASED_LOW                  = 2;
  361.   IMAGE_REL_BASED_HIGHLOW              = 3;
  362.   IMAGE_REL_BASED_HIGHADJ              = 4;
  363.   IMAGE_REL_BASED_MIPS_JMPADDR         = 5;
  364.  
  365. //
  366. // Line number format.
  367. //
  368. type
  369.   TImageLineNumber = packed record
  370.     case integer of
  371.       0 : (SymbolTableIndex: DWORD; // Symbol table index of function name if Linenumber is 0.
  372.            Linenumber      : WORD); // Line number.
  373.       1 : (VirtualAddress  : DWORD; // Virtual address of line number.
  374.            Linenumber_     : WORD);
  375.   end;
  376. const
  377.   IMAGE_SIZEOF_LINENUMBER         = 6;
  378.  
  379. //
  380. // Archive format.
  381. //
  382.   IMAGE_ARCHIVE_START_SIZE             = 8;
  383.   IMAGE_ARCHIVE_START                  = '!<arch>'#13#10;
  384.   IMAGE_ARCHIVE_END                    = '`'#13#10;
  385.   IMAGE_ARCHIVE_PAD                    = #13#10;
  386.   IMAGE_ARCHIVE_LINKER_MEMBER          = '/               ';
  387.   IMAGE_ARCHIVE_LONGNAMES_MEMBER       = '//              ';
  388.  
  389. type
  390.   PImageArchiveMemberHeader = ^TImageArchiveMemberHeader;
  391.   TImageArchiveMemberHeader = packed record
  392.     Name     : array[0..16-1] of BYTE; // File member name - `/' terminated.
  393.     Date     : array[0..12-1] of BYTE; // File member date - decimal.
  394.     UserID   : array[0.. 6-1] of BYTE; // File member user id - decimal.
  395.     GroupID  : array[0.. 6-1] of BYTE; // File member group id - decimal.
  396.     Mode     : array[0.. 8-1] of BYTE; // File member mode - octal.
  397.     Size     : array[0..10-1] of BYTE; // File member size - decimal.
  398.     EndHeader: array[0.. 2-1] of BYTE; // String to end header.
  399.   end;
  400. const
  401.   IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR     = 60;
  402.  
  403. //
  404. // DLL support.
  405. //
  406.  
  407. //
  408. // Export Format
  409. //
  410. type
  411.   PPDWORD = ^PDWORD;
  412.   PPWORD  = ^PWORD;
  413.   PImageExportDirectory = ^TImageExportDirectory;
  414.   TImageExportDirectory = packed record
  415.     Characteristics:        DWORD;
  416.     TimeDateStamp:          DWORD;
  417.     MajorVersion:           WORD;
  418.     MinorVersion:           WORD;
  419.     Name:                   DWORD;
  420.     Base:                   DWORD;
  421.     NumberOfFunctions:      DWORD;
  422.     NumberOfNames:          DWORD;
  423.     AddressOfFunctions:     PPDWORD;
  424.     AddressOfNames:         PPDWORD;
  425.     AddressOfNameOrdinals:  PPWORD;
  426.   end;
  427.  
  428. //
  429. // Import Format
  430. //
  431.   PImageImportByName = ^TImageImportByName;
  432.   TImageImportByName = packed record
  433.     Hint : WORD;
  434.     Name : array[0..255] of Char;
  435.   end;
  436.  
  437.   PImageThunkData = ^TImageThunkData;
  438.   TImageThunkData = packed record
  439.     case integer of
  440.       0 : (ForwarderString: PBYTE);
  441.       1 : (FunctionPtr    : PDWORD);
  442.       2 : (Ordinal        : DWORD);
  443.       3 : (AddressOfData  : PImageImportByName);
  444.   end;
  445.  
  446. const
  447.   IMAGE_ORDINAL_FLAG  =  DWORD($80000000);
  448. // Make functions?:
  449. {##  IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0)
  450.   IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)}
  451.  
  452. type
  453.   PImageImportDescriptor = ^TImageImportDescriptor;
  454.   TImageImportDescriptor = packed record
  455.      HintNameTableOffset: DWORD;    // RVA to original unbound IAT, aka Characteristics
  456.                                     // 0 for terminating null import descriptor
  457.                                     // PImageThunkData
  458.      TimeDateStamp      : DWORD;    // 0 if not bound,
  459.                                     // -1 if bound, and real date\time stamp
  460.                                     //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
  461.                                     // O.W. date/time stamp of DLL bound to (Old BIND)
  462.       ForwarderChain    : DWORD;    // -1 if no forwarders
  463.       NameOffset        : DWORD;    // RVA to name of the module we're importing from
  464.       IATOffset         : DWORD;    // RVA to IAT (if bound this IAT has actual addresses)
  465.                                     // PImageThunkData
  466.   end;
  467.  
  468.  
  469. //
  470. // New format import descriptors pointed to by DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ]
  471. //
  472. type
  473.   PImageBoundImportDescriptor = ^TImageBoundImportDescriptor;
  474.   TImageBoundImportDescriptor = packed record
  475.     TimeDateStamp               : DWORD;
  476.     OffsetModuleName            : WORD;
  477.     NumberOfModuleForwarderRefs : WORD;
  478.     // Array of zero or more IMAGE_BOUND_FORWARDER_REF follows
  479.   end;
  480.  
  481.   TImageBoundForwarderRef = packed record
  482.     TimeDateStamp    : DWORD;
  483.     OffsetModuleName : WORD;
  484.     Reserved         : WORD;
  485.   end;
  486. // ------------------------- END-OF-WINNT.H-STUFF -----------------------------
  487.  
  488. // Utility routines:
  489.  
  490. function GetImageNtHeader(Base: Pointer): PImageNtHeaders;
  491. function GetSectionHeader(NtHeader: PImageNtHeaders; SectionName: PChar): PImageSectionHeader;
  492. function GetFirstSectionHeader(NtHeader: PImageNtHeaders): PImageSectionHeader;
  493.  
  494. type
  495.   EHookError = class(Exception);
  496.  
  497. implementation
  498.  
  499. procedure HookError(const Msg: string);
  500. begin
  501.   raise EHookError.Create(Msg);
  502. end;
  503.  
  504. function GetImageNtHeader(Base: Pointer): PImageNtHeaders;
  505. var
  506.   DOSHeader: PImageDOSHeader;
  507. begin
  508.   DOSHeader := PImageDOSHeader(Base);
  509.   if DOSHeader.e_magic <> IMAGE_DOS_SIGNATURE then HookError('Not a valid MZ-file!');
  510.   Result := PImageNtHeaders(DWORD(Base) + DOSHeader.e_lfanew);
  511.   if Result.Signature <> IMAGE_NT_SIGNATURE then HookError('Not a valid PE-file!');
  512. end;
  513.  
  514. function GetSectionHeader(NtHeader: PImageNtHeaders; SectionName: PChar): PImageSectionHeader;
  515. var
  516.   i : integer;
  517. begin
  518.   Result := PImageSectionHeader(DWORD(NtHeader) + SizeOf(NtHeader^));
  519.   for i := 0 to NtHeader.FileHeader.NumberOfSections-1 do
  520.   begin
  521.     if StrIComp(PChar(@Result.Name), SectionName) = 0 then
  522.       Exit;
  523.     Inc(Result);
  524.   end;
  525.   HookError(Format('Could not find %s section', [SectionName]));
  526. end;
  527.  
  528. function GetFirstSectionHeader(NtHeader: PImageNtHeaders): PImageSectionHeader;
  529. begin
  530.   Result := PImageSectionHeader(DWORD(NtHeader) + SizeOf(NtHeader^));
  531. end;
  532.  
  533. end.